package com.ruoyi.web.controller.system;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.aigc.generation.models.QwenParam;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.domain.Feedback;
import com.ruoyi.system.domain.ProjectFeedback;
import com.ruoyi.system.domain.Standard;
import com.ruoyi.system.service.IFeedbackService;
import com.ruoyi.system.service.IProjectFeedbackService;
import com.ruoyi.system.service.IStandardService;
import io.reactivex.Flowable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.time.Duration;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

@RestController
@RequestMapping(value = "/ai")
@PropertySource({"classpath:application.properties"})
public class AIController {

    @Value("${ai-api-key}")
    private String apiKey;

    @Autowired
    private IFeedbackService feedbackService;

    @Autowired
    private IProjectFeedbackService projectFeedbackService;

    @Autowired
    private IStandardService standardService;

    @Anonymous
    @GetMapping(value = "/solveProject")
    public AjaxResult solveProject() throws Exception {
        List<ProjectFeedback> projectFeedbacks = projectFeedbackService.selectProjectFeedbackList(new ProjectFeedback());
        for (ProjectFeedback projectFeedback : projectFeedbacks) {
            if (projectFeedback.getResolution() == null || Objects.equals(projectFeedback.getResolution(), "")) {
//                System.out.println(projectFeedback.getResolution());
                Generation gen = new Generation();
                Message msg = Message.builder().role(Role.USER.getValue()).content(projectFeedback.getIssueDescription()+"直接给出解决方案，不需要回答其他，并且方案在30个字以内").build();
                QwenParam param = QwenParam.builder()
                        .model(Generation.Models.QWEN_PLUS)
                        .messages(Arrays.asList(msg))
                        .resultFormat(QwenParam.ResultFormat.MESSAGE)
                        .topP(0.8)
                        .enableSearch(true)
                        .apiKey(apiKey)
                        .incrementalOutput(false)
                        .build();
                Flowable<GenerationResult> result = gen.streamCall(param);
                Flux.from(result)
                        .delayElements(Duration.ofMillis(1000))
                        .map(message -> {
                            String output = message.getOutput().getChoices().get(0).getMessage().getContent();
                            projectFeedback.setResolution(output);
                            LocalDate currentDate = LocalDate.now();
                            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                            String formattedDate = currentDate.format(formatter);
                            projectFeedback.setResolvedDatetime(formattedDate);
                            projectFeedback.setStatus("已处理");
                            return ServerSentEvent.<String>builder()
                                    .data(output)
                                    .build();
                        })
                        .doOnComplete(() -> { // Update the Feedback object after all answers are processed
                          projectFeedbackService.updateProjectFeedback(projectFeedback);
                        })
                        .doOnError(e -> { // Handle exceptions
                            if (e instanceof NoApiKeyException) {
                                // 处理 NoApiKeyException
                            } else if (e instanceof InputRequiredException) {
                                // 处理 InputRequiredException
                            } else if (e instanceof ApiException) {
                                // 处理其他 ApiException
                            } else {
                                // 处理其他未知异常
                            }
                        })
                        .subscribe(); // Subscribe to the Flux to trigger the execution
            }
        }
        return AjaxResult.success();
    }

    @Anonymous
    @GetMapping(value = "/sloveLive")
    public AjaxResult solveLive() throws Exception {
        List<Feedback> feedbacks = feedbackService.selectFeedbackList(new Feedback());
        for (Feedback feedback : feedbacks) {
            if (feedback.getFdMethod()==null|| Objects.equals(feedback.getFdMethod(), "")) {
//                System.out.println(projectFeedback.getResolution());
                Generation gen = new Generation();
                Message msg = Message.builder().role(Role.USER.getValue()).content(feedback.getFdContent()+"直接给出解决方案，不需要回答其他，并且方案在50个字以内").build();
                QwenParam param = QwenParam.builder()
                        .model(Generation.Models.QWEN_PLUS)
                        .messages(Arrays.asList(msg))
                        .resultFormat(QwenParam.ResultFormat.MESSAGE)
                        .topP(0.8)
                        .enableSearch(true)
                        .apiKey(apiKey)
                        .incrementalOutput(false)
                        .build();
                Flowable<GenerationResult> result = gen.streamCall(param);
                Flux.from(result)
                        .delayElements(Duration.ofMillis(1000))
                        .map(message -> {
                            String output = message.getOutput().getChoices().get(0).getMessage().getContent();
                            feedback.setFdMethod(output);
                            LocalDate currentDate = LocalDate.now();
                            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                            String formattedDate = currentDate.format(formatter);
                            feedback.setFdEtime(formattedDate);
                            feedback.setFdStu("已处理");
//
                            return ServerSentEvent.<String>builder()
                                    .data(output)
                                    .build();
                        })
                        .doOnComplete(() -> { // Update the Feedback object after all answers are processed

                            feedbackService.updateFeedback(feedback);
                        })
                        .doOnError(e -> { // Handle exceptions
                            if (e instanceof NoApiKeyException) {
                                // 处理 NoApiKeyException
                            } else if (e instanceof InputRequiredException) {
                                // 处理 InputRequiredException
                            } else if (e instanceof ApiException) {
                                // 处理其他 ApiException
                            } else {
                                // 处理其他未知异常
                            }
                        })
                        .subscribe(); // Subscribe to the Flux to trigger the execution
            }
        }
        return AjaxResult.success();
    }

    @Anonymous
    @GetMapping(value = "/dealOne/{feedbackId}")
    public   AjaxResult dealOne(@PathVariable Long feedbackId) throws Exception {
        Feedback feedback = feedbackService.selectFeedbackByFdId(feedbackId);
        if (feedback.getFdMethod()== null || Objects.equals(feedback.getFdMethod(), "")) {
//                System.out.println(projectFeedback.getResolution());
            Generation gen = new Generation();
            Message msg = Message.builder().role(Role.USER.getValue()).content(feedback.getFdContent()+"直接给出解决方案，不需要回答其他，并且方案在50个字以内").build();
            QwenParam param = QwenParam.builder()
                    .model(Generation.Models.QWEN_PLUS)
                    .messages(Arrays.asList(msg))
                    .resultFormat(QwenParam.ResultFormat.MESSAGE)
                    .topP(0.8)
                    .enableSearch(true)
                    .apiKey(apiKey)
                    .incrementalOutput(false)
                    .build();
            Flowable<GenerationResult> result = gen.streamCall(param);
            Flux.from(result)
                    .delayElements(Duration.ofMillis(1000))
                    .map(message -> {
                        String output = message.getOutput().getChoices().get(0).getMessage().getContent();
                        feedback.setFdMethod(output);
                        LocalDate currentDate = LocalDate.now();
                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                        String formattedDate = currentDate.format(formatter);
                        feedback.setFdEtime(formattedDate);
                        feedback.setFdStu("已处理");
//                            projectFeedback.setResolvedDatetime(formattedDate);
//                            projectFeedback.setStatus("已处理");
                        return ServerSentEvent.<String>builder()
                                .data(output)
                                .build();
                    })
                    .doOnComplete(() -> { // Update the Feedback object after all answers are processed
//                            projectFeedbackService.updateProjectFeedback(projectFeedback);
                        feedbackService.updateFeedback(feedback);
                    })
                    .doOnError(e -> { // Handle exceptions
                        if (e instanceof NoApiKeyException) {
                            // 处理 NoApiKeyException
                        } else if (e instanceof InputRequiredException) {
                            // 处理 InputRequiredException
                        } else if (e instanceof ApiException) {
                            // 处理其他 ApiException
                        } else {
                            // 处理其他未知异常
                        }
                    })
                    .subscribe(); // Subscribe to the Flux to trigger the execution
        }
        return AjaxResult.success();
    }

    @Anonymous
    @GetMapping(value = "/tackleOne/{projectFeedbackId}")
    public   AjaxResult tackleOne(@PathVariable Long projectFeedbackId) throws Exception {
        ProjectFeedback  projectFeedback= projectFeedbackService.selectProjectFeedbackByFeedbackId(projectFeedbackId);
        if (projectFeedback.getResolution()== null || Objects.equals(projectFeedback.getResolution(), "")) {
//                System.out.println(projectFeedback.getResolution());
            Generation gen = new Generation();
            Message msg = Message.builder().role(Role.USER.getValue()).content(projectFeedback.getIssueDescription()+"直接给出解决方案，不需要回答其他，并且方案在50个字以内").build();
            QwenParam param = QwenParam.builder()
                    .model(Generation.Models.QWEN_PLUS)
                    .messages(Arrays.asList(msg))
                    .resultFormat(QwenParam.ResultFormat.MESSAGE)
                    .topP(0.8)
                    .enableSearch(true)
                    .apiKey(apiKey)
                    .incrementalOutput(false)
                    .build();
            Flowable<GenerationResult> result = gen.streamCall(param);
            Flux.from(result)
                    .delayElements(Duration.ofMillis(1000))
                    .map(message -> {
                        String output = message.getOutput().getChoices().get(0).getMessage().getContent();
//                        feedback.setFdMethod(output);
                        projectFeedback.setResolution(output);
                        LocalDate currentDate = LocalDate.now();
                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
                        String formattedDate = currentDate.format(formatter);
                        projectFeedback.setResolvedDatetime(formattedDate);
                        projectFeedback.setStatus("已处理");
//                            projectFeedback.setResolvedDatetime(formattedDate);
//                            projectFeedback.setStatus("已处理");
                        return ServerSentEvent.<String>builder()
                                .data(output)
                                .build();
                    })
                    .doOnComplete(() -> { // Update the Feedback object after all answers are processed
//                            projectFeedbackService.updateProjectFeedback(projectFeedback);
                        projectFeedbackService.updateProjectFeedback(projectFeedback);
                    })
                    .doOnError(e -> { // Handle exceptions
                        if (e instanceof NoApiKeyException) {
                            // 处理 NoApiKeyException
                        } else if (e instanceof InputRequiredException) {
                            // 处理 InputRequiredException
                        } else if (e instanceof ApiException) {
                            // 处理其他 ApiException
                        } else {
                            // 处理其他未知异常
                        }
                    })
                    .subscribe(); // Subscribe to the Flux to trigger the execution
        }
        return AjaxResult.success();
    }

    @Anonymous
    @GetMapping(value = "/devPlan")
    public AjaxResult devPlan() throws Exception {
        List<Standard>standards = standardService.selectStandardList(new Standard());
        for (Standard standard : standards) {
            if (standard.getStandardContent() == null || Objects.equals(standard.getStandardContent(), "")) {
//
                // 创建Generation实例，用于调用文本生成服务
                Generation gen = new Generation();

// 构建请求消息，定义评估对象和期望的评估标准形式
                Message msg = Message.builder()
                        .role(Role.USER.getValue()) // 设置角色为用户
                        .content("根据这个评估对象：" + standard.getTarget() + "，直接给出50字以内的详细的评估标准") // 消息内容，包含评估对象信息
                        .build();

// 配置生成参数，指定模型、消息、结果格式等
                QwenParam param = QwenParam.builder()
                        .model(Generation.Models.QWEN_PLUS) // 选择使用的模型为Qwen Plus
                        .messages(Arrays.asList(msg)) // 使用之前构建的消息
                        .resultFormat(QwenParam.ResultFormat.MESSAGE) // 设置返回结果的格式为消息
                        .topP(0.8) // 设置top-p采样参数
                        .enableSearch(true) // 启用搜索增强功能
                        .apiKey(apiKey) // 设置API密钥
                        .incrementalOutput(false) // 禁止增量输出
                        .build();

// 调用生成服务，获取一个流式的生成结果
                Flowable<GenerationResult> result = gen.streamCall(param);

// 将Flowable转换为Flux，以便于使用Reactor库进行流处理
// 延迟每个元素的处理时间，便于观察或控制输出频率
// 映射每个消息结果，提取内容，更新standard对象的评估标准和时间戳
// 构建ServerSentEvent对象用于服务器推送数据到客户端
                Flux.from(result)
                        .delayElements(Duration.ofMillis(1000)) // 每个结果之间延迟1秒
                        .map(message -> {
                            String output = message.getOutput().getChoices().get(0).getMessage().getContent(); // 获取生成的文本内容
                            standard.setStandardContent(output); // 更新standard的评估标准内容
                            LocalDate currentDate = LocalDate.now(); // 获取当前日期
                            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); // 定义日期格式
                            String formattedDate = currentDate.format(formatter); // 格式化当前日期
                            standard.setTime(formattedDate); // 更新standard的时间戳
                            // 构建ServerSentEvent对象，包含生成的文本内容，用于实时推送
                            return ServerSentEvent.<String>builder()
                                    .data(output)
                                    .build();
                        })
                        // 在所有生成结果处理完毕后，执行更新standard到数据库的操作
                        .doOnComplete(() -> standardService.updateStandard(standard))
                        .doOnError(e -> { // Handle exceptions
                            if (e instanceof NoApiKeyException) {
                                // 处理 NoApiKeyException
                            } else if (e instanceof InputRequiredException) {
                                // 处理 InputRequiredException
                            } else if (e instanceof ApiException) {
                                // 处理其他 ApiException
                            } else {
                                // 处理其他未知异常
                            }
                        })
                        .subscribe(); // Subscribe to the Flux to trigger the execution
            }
        }
        return AjaxResult.success();
    }
}
